This blog post is part of the mini series about Framework Design Principles.

A framework or library should make it really easy to write readable code. I guess we read more code than we write, so reading code is probably more important than writing code. That makes writing readable code mandatory.

Reading code means trying to figure out what it does. This means processing a lot of information in our mind - within our “working memory”.

working memory

Unfortunately our working memory is limited to about 3-5 items. If we have to process more items they have to be constantly “loaded” from long term memory or our sensory organs. The good news is: The size of these items is almost unlimited. By building junks of information we can keep more in working memory. When we think of the term “context free grammar” we can process it as a single concept - that is, one item, not as a sequence of 20 letters. (*)

But: What does this have to do with readability? The idea is pretty simple: Help the reader to build junks of information and to minimize “cache misses” - that is, loading from long term memory. To achieve this, the immediate surroundings of some piece of code should give the user hints about how it works and how to modify it.

Fluent interfaces

Let’s start with a negative example. Some frameworks force their users to write code like this:

new User(
	„David“, „Tanzer“,
	„foo@bar.com“,
	„secret“,
	Roles.USER);

While this code is quite easy to write, it can be really hard to read. There is no way to find out what the parameters mean by looking at this code. You either have to read the API documention or open the User-class. You might say that this is not a lot of work, but still, it is annoying. Nobody reads the documentation, don’t make me do it.

There’s a nice solution to this problem called “fluent interfaces” or “method chaining”: Instead of one method/constructor with lots of parameters define lots of methods with a single parameter. This example is from Apache Wicket:

add(new Label("id")
	.setMarkupId("mid")
	.setVisible(true)
	.setEnabled(false)
);

It is a little bit harder to write (but still no problem when you have auto complete in your IDE) and much easier to read. A lot of the things you need to know are right there, before our eyes.

There are two minor problems with this approach: First, you can not use it for mandatory parameters (because you can not guarantee that all the methods are called). Second, in a statically typed language like Java, once you call a method from the base class, the compiler does not know the child class methods anymore. The compiler could fix that, but I would not wait for it. You could use generics, but that can become ugly.

Named Parameters

Named parameters would be really nice here. Something like Smalltalk has:

collection copyFrom: 1 to: 10

This code sends the message “copyFrom:to:” to the object “collection”. The parameters are called “copyFrom” and “to”, their values are “1” and “10”. Unfortunately, in Java we don’t have a feature like this. We could simulate named parameters when initializing objects using Double Brace Initialization:

persistUser(

	new User(){{
		userName="david";
		password="secret";
}});

But this also has some disadvantages. First, it can not be used for mandatory parameters (same reason as above). Second, this creates an anonymous class that is derived from “User”. So, if the class “User” uses a naive implementaion of “equals” like the following (very common in java) it does not work.

public boolean equals(Object other) {
	//...check for null...
	
	if(getClass().equals(other.getClass) {
		//...test if the objects are equal...
	}
	return false;
}

And third: A lot of Java programmers don’t know this. But I guess that does not count as an argument because every programmer should be able to learn it.

Other techniques, conclusion

There are other techniques we can use to allow users of our framework or library to write readable code. The Single responsibility principle (SRP) and Single Level of Abstraction (SLA) come to mid. Ralf Westphal has a good step by step explanation of SLA in his blog.

When writing code that others have to use, we should think more often: “Does this allow the users of my code to write easier readable code?” - This is in essence all I wanted to say with this blog post.

(*) I am no brain scientist. This description is probabyl a gross oversimplification, but it is good enough for this blog post.